{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WMucfLUS1yhH"
      },
      "source": [
        "# LSTM Recurrent Neural Network\n",
        "\n",
        "## Learning Objectives\n",
        "\n",
        "1. Create map for converting IMDB dataset to readable reviews.\n",
        "2. Create and build LSTM Recurrent Neural Network.\n",
        "3. Visualise the Model and train the LSTM.\n",
        "4. Evaluate model with test data and view results.\n",
        "\n",
        "\n",
        "## What is this?\n",
        "\n",
        "This Jupyter Notebook contains Python code for building a LSTM Recurrent Neural Network that gives 87-88% accuracy on the IMDB Movie Review Sentiment Analysis Dataset. \n",
        "\n",
        "More information is given on [this blogpost](https://www.bouvet.no/bouvet-deler/explaining-recurrent-neural-networks).\n",
        "\n",
        "## Introduction \n",
        "Long Short Term Memory networks – usually just called “LSTMs” – are a special kind of RNN, capable of learning long-term dependencies. They were introduced by Hochreiter & Schmidhuber (1997), and were refined and popularized by many people in following work. They work tremendously well on a large variety of problems, and are now widely used.\n",
        "\n",
        "LSTMs are explicitly designed to avoid the long-term dependency problem. Remembering information for long periods of time is practically their default behavior, not something they struggle to learn!\n",
        "\n",
        "\n",
        "Each learning objective will correspond to a __#TODO__ in the [student lab notebook](../labs/LSTM_IMDB_Sentiment_Example.ipynb) -- try to complete that notebook first before reviewing this solution notebook."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WP1VrbVp3sVu"
      },
      "source": [
        "## Setting up\n",
        "\n",
        "When running this for the first time you may get a warning telling you to restart the Runtime. You can ignore this, but feel free to select \"Kernel->Restart Kernel\" from the overhead menu if you encounter problems."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2e3txwbh3q76",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 531
        },
        "outputId": "e42b88ff-fa1d-4b9c-df9f-c5b7557ce2fb"
      },
      "source": [
        "# keras.datasets.imdb is broken in TensorFlow 1.13 and 1.14 due to numpy 1.16.3\n",
        "!pip install numpy==1.16.2\n",
        "\n",
        "# All the imports!\n",
        "import tensorflow as tf \n",
        "import numpy as np\n",
        "from tensorflow.keras.preprocessing import sequence\n",
        "from numpy import array\n",
        "\n",
        "# Supress deprecation warnings\n",
        "import logging\n",
        "logging.getLogger('tensorflow').disabled = True\n",
        "\n",
        "# Fetch \"IMDB Movie Review\" data, constraining our reviews to \n",
        "# the 10000 most commonly used words\n",
        "vocab_size = 10000\n",
        "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.imdb.load_data(num_words=vocab_size)\n",
        "\n",
        "# Map for readable classnames\n",
        "class_names = [\"Negative\", \"Positive\"]"
      ],
      "execution_count": 1,
      "outputs": [
        {
         "name": "stdout",
         "output_type": "stream",
         "text": [
          "Collecting numpy==1.16.2\n",
          "  Downloading numpy-1.16.2-cp37-cp37m-manylinux1_x86_64.whl (17.3 MB)\n",
          "\u001b[K     |████████████████████████████████| 17.3 MB 6.1 MB/s eta 0:00:01\n",
          "\u001b[?25hInstalling collected packages: numpy\n",
          "  Attempting uninstall: numpy\n",
          "    Found existing installation: numpy 1.19.5\n",
          "    Uninstalling numpy-1.19.5:\n",
          "      Successfully uninstalled numpy-1.19.5\n",
          "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
          "tensorflow-io 0.18.0 requires tensorflow-io-gcs-filesystem==0.18.0, which is not installed.\n",
          "explainable-ai-sdk 1.3.2 requires xai-image-widget, which is not installed.\n",
          "tfx-bsl 1.3.0 requires absl-py<0.13,>=0.9, but you have absl-py 0.14.0 which is incompatible.\n",
          "tfx-bsl 1.3.0 requires google-api-python-client<2,>=1.7.11, but you have google-api-python-client 2.22.0 which is incompatible.\n",
          "tfx-bsl 1.3.0 requires pyarrow<3,>=1, but you have pyarrow 5.0.0 which is incompatible.\n",
          "tfx-bsl 1.3.0 requires tensorflow!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,<3,>=1.15.2, but you have tensorflow 2.6.0 which is incompatible.\n",
          "tensorflow 2.6.0 requires numpy~=1.19.2, but you have numpy 1.16.2 which is incompatible.\n",
          "tensorflow-transform 1.3.0 requires absl-py<0.13,>=0.9, but you have absl-py 0.14.0 which is incompatible.\n",
          "tensorflow-transform 1.3.0 requires pyarrow<3,>=1, but you have pyarrow 5.0.0 which is incompatible.\n",
          "tensorflow-transform 1.3.0 requires tensorflow!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,<2.7,>=1.15.2, but you have tensorflow 2.6.0 which is incompatible.\n",
          "tensorflow-serving-api 2.6.0 requires tensorflow<3,>=2.6.0, but you have tensorflow 2.6.0 which is incompatible.\n",
          "scipy 1.7.1 requires numpy<1.23.0,>=1.16.5, but you have numpy 1.16.2 which is incompatible.\n",
          "scikit-image 0.18.3 requires numpy>=1.16.5, but you have numpy 1.16.2 which is incompatible.\n",
          "pyarrow 5.0.0 requires numpy>=1.16.6, but you have numpy 1.16.2 which is incompatible.\n",
          "phik 0.11.2 requires numpy>=1.18.0, but you have numpy 1.16.2 which is incompatible.\n",
          "pandas 1.3.3 requires numpy>=1.17.3, but you have numpy 1.16.2 which is incompatible.\n",
          "numba 0.54.0 requires numpy<1.21,>=1.17, but you have numpy 1.16.2 which is incompatible.\n",
          "apache-beam 2.32.0 requires dill<0.3.2,>=0.3.1.1, but you have dill 0.3.4 which is incompatible.\n",
          "apache-beam 2.32.0 requires pyarrow<5.0.0,>=0.15.1, but you have pyarrow 5.0.0 which is incompatible.\u001b[0m\n",
          "Successfully installed numpy-1.16.2\n"
         ]
        },
        {
         "name": "stderr",
         "output_type": "stream",
         "text": [
          "2021-09-27 14:33:12.028514: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0\n"
         ]
        },
        {
         "name": "stdout",
         "output_type": "stream",
         "text": [
          "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb.npz\n",
          "17465344/17464789 [==============================] - 0s 0us/step\n"
         ]
        }
      ]
    },
    {
     "cell_type": "markdown",
     "metadata": {
      "id": "sawo1x8kQk9b"
     },
     "source": [
       "**Note: Please ignore any incompatibility errors or warnings as it does not impact the notebook's functionality.**"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "This notebook uses TF2.x.\n",
      "Please check your tensorflow version using the cell below."
     ]
    },
    {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TensorFlow version:  2.x.x\n"
     ]
    }
   ],
   "source": [
    "# Show the currently installed version of TensorFlow\n",
    "print(\"TensorFlow version: \",tf.version.VERSION)"
     ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hdyHL8FF0JJy"
      },
      "source": [
        "## Create map for converting IMDB dataset to readable reviews\n",
        "\n",
        "Reviews in the IMDB dataset have been encoded as a sequence of integers. Luckily the dataset also \n",
        "contains an index for converting the reviews back into human readable form."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "E05AweFu0Imt",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "d4c48cc1-1549-42b3-ddd9-abb3f343d6ab"
      },
      "source": [
        "# Get the word index from the dataset\n",
        "word_index = tf.keras.datasets.imdb.get_word_index()\n",
        "\n",
        "# Ensure that \"special\" words are mapped into human readable terms \n",
        "word_index = {k:(v+3) for k,v in word_index.items()}\n",
        "word_index[\"<PAD>\"] = 0\n",
        "word_index[\"<START>\"] = 1\n",
        "word_index[\"<UNKNOWN>\"] = 2\n",
        "word_index[\"<UNUSED>\"] = 3\n",
        "\n",
        "# Perform reverse word lookup and make it callable\n",
        "# TODO\n",
        "reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])\n",
        "def decode_review(text):\n",
        "    return ' '.join([reverse_word_index.get(i, '?') for i in text])"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb_word_index.json\n",
            "1646592/1641221 [==============================] - 0s 0us/step\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fFXK-g6G81sC"
      },
      "source": [
        "## Data Insight\n",
        "\n",
        "Here we take a closer look at our data. How many words do our reviews contain?\n",
        "\n",
        "And what do our reviews look like in machine and human readable form?\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yD1qHVBn81Y_",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "b313242c-0536-4b4d-d9ec-d895cfdc7c35"
      },
      "source": [
        "# Concatenate test and training datasets\n",
        "allreviews = np.concatenate((x_train, x_test), axis=0)\n",
        "\n",
        "# Review lengths across test and training whole datasets\n",
        "print(\"Maximum review length: {}\".format(len(max((allreviews), key=len))))\n",
        "print(\"Minimum review length: {}\".format(len(min((allreviews), key=len))))\n",
        "result = [len(x) for x in allreviews]\n",
        "print(\"Mean review length: {}\".format(np.mean(result)))\n",
        "\n",
        "# Print a review and it's class as stored in the dataset. Replace the number\n",
        "# to select a different review.\n",
        "print(\"\")\n",
        "print(\"Machine readable Review\")\n",
        "print(\"  Review Text: \" + str(x_train[60]))\n",
        "print(\"  Review Sentiment: \" + str(y_train[60]))\n",
        "\n",
        "# Print a review and it's class in human readable format. Replace the number\n",
        "# to select a different review.\n",
        "print(\"\")\n",
        "print(\"Human Readable Review\")\n",
        "print(\"  Review Text: \" + decode_review(x_train[60]))\n",
        "print(\"  Review Sentiment: \" + class_names[y_train[60]])"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Maximum review length: 2494\n",
            "Minimum review length: 7\n",
            "Mean review length: 234.75892\n",
            "\n",
            "Machine readable Review\n",
            "  Review Text: [1, 13, 219, 14, 33, 4, 2, 22, 1413, 12, 16, 373, 175, 2711, 1115, 1026, 430, 939, 16, 23, 2444, 25, 43, 697, 89, 12, 16, 170, 8, 130, 262, 19, 32, 4, 665, 7, 4, 2, 322, 5, 4, 1520, 7, 4, 86, 250, 10, 10, 4, 249, 173, 16, 4, 3891, 6, 19, 4, 167, 564, 5, 564, 1325, 36, 805, 8, 216, 638, 17, 2, 21, 25, 100, 376, 507, 4, 2110, 15, 79, 125, 23, 567, 13, 2134, 233, 36, 4852, 2, 5, 81, 1672, 10, 10, 92, 437, 129, 58, 13, 69, 8, 401, 61, 1432, 39, 1286, 46, 7, 12]\n",
            "  Review Sentiment: 0\n",
            "\n",
            "Human Readable Review\n",
            "  Review Text: <START> i saw this at the <UNKNOWN> film festival it was awful every clichéd violent rich boy fantasy was on display you just knew how it was going to end especially with all the shots of the <UNKNOWN> wife and the rape of the first girl br br the worst part was the q a with the director writer and writer producer they tried to come across as <UNKNOWN> but you could tell they're the types that get off on violence i bet anything they frequent <UNKNOWN> and do drugs br br don't waste your time i had to keep my boyfriend from walking out of it\n",
            "  Review Sentiment: Negative\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mF-Votm66zD5"
      },
      "source": [
        "## Pre-processing Data\n",
        "\n",
        "We need to make sure that our reviews are of a uniform length. This is for the LSTM's parameters.\n",
        "\n",
        "Some reviews will need to be truncated, while others need to be padded."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uNtJTLJA6gaT",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "bb552c79-32d9-4a4c-d102-b3f56dfa4bb0"
      },
      "source": [
        "# The length of reviews\n",
        "review_length = 500\n",
        "\n",
        "# Padding / truncated our reviews\n",
        "x_train = sequence.pad_sequences(x_train, maxlen = review_length)\n",
        "x_test = sequence.pad_sequences(x_test, maxlen = review_length)\n",
        "\n",
        "# Check the size of our datasets. Review data for both test and training should \n",
        "# contain 25000 reviews of 500 integers. Class data should contain 25000 values, \n",
        "# one for each review. Class values are 0 or 1, indicating a negative \n",
        "# or positive review.\n",
        "print(\"Shape Training Review Data: \" + str(x_train.shape))\n",
        "print(\"Shape Training Class Data: \" + str(y_train.shape))\n",
        "print(\"Shape Test Review Data: \" + str(x_test.shape))\n",
        "print(\"Shape Test Class Data: \" + str(y_test.shape))\n",
        "\n",
        "# Note padding is added to start of review, not the end\n",
        "print(\"\")\n",
        "print(\"Human Readable Review Text (post padding): \" + decode_review(x_train[60]))"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Shape Training Review Data: (25000, 500)\n",
            "Shape Training Class Data: (25000,)\n",
            "Shape Test Review Data: (25000, 500)\n",
            "Shape Test Class Data: (25000,)\n",
            "\n",
            "Human Readable Review Text (post padding): <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <START> i saw this at the <UNKNOWN> film festival it was awful every clichéd violent rich boy fantasy was on display you just knew how it was going to end especially with all the shots of the <UNKNOWN> wife and the rape of the first girl br br the worst part was the q a with the director writer and writer producer they tried to come across as <UNKNOWN> but you could tell they're the types that get off on violence i bet anything they frequent <UNKNOWN> and do drugs br br don't waste your time i had to keep my boyfriend from walking out of it\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BfOdV_VCCFee"
      },
      "source": [
        "## Create and build LSTM Recurrent Neural Network"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8nmO8M4aCKwT",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "365cce8d-be9a-427e-89bc-3a9940689edd"
      },
      "source": [
        "# We begin by defining an empty stack. We'll use this for building our \n",
        "# network, later by layer.\n",
        "model = tf.keras.models.Sequential()\n",
        "\n",
        "# The Embedding Layer provides a spatial mapping (or Word Embedding) of all the \n",
        "# individual words in our training set. Words close to one another share context \n",
        "# and or meaning. This spatial mapping is learning during the training process.\n",
        "model.add(\n",
        "    tf.keras.layers.Embedding(\n",
        "        input_dim = vocab_size, # The size of our vocabulary \n",
        "        output_dim = 32, # Dimensions to which each words shall be mapped\n",
        "        input_length = review_length # Length of input sequences\n",
        "    )\n",
        ")\n",
        "\n",
        "# Dropout layers fight overfitting and forces the model to learn multiple \n",
        "# representations of the same data by randomly disabling neurons in the \n",
        "# learning phase.\n",
        "# TODO \n",
        "model.add(\n",
        "    tf.keras.layers.Dropout(\n",
        "        rate=0.25 # Randomly disable 25% of neurons\n",
        "    )\n",
        ")\n",
        "\n",
        "# We are using a fast version of LSTM which is optimised for GPUs. This layer \n",
        "# looks at the sequence of words in the review, along with their word embeddings\n",
        "# and uses both of these to determine the sentiment of a given review.\n",
        "# TODO \n",
        "model.add(\n",
        "    tf.keras.layers.LSTM(\n",
        "        units=32 # 32 LSTM units in this layer\n",
        "    )\n",
        ")\n",
        "\n",
        "# Add a second dropout layer with the same aim as the first.\n",
        "# TODO \n",
        "model.add(\n",
        "    tf.keras.layers.Dropout(\n",
        "        rate=0.25 # Randomly disable 25% of neurons\n",
        "    )\n",
        ")\n",
        "\n",
        "# All LSTM units are connected to a single node in the dense layer. A sigmoid \n",
        "# activation function determines the output from this node - a value \n",
        "# between 0 and 1. Closer to 0 indicates a negative review. Closer to 1 \n",
        "# indicates a positive review.\n",
        "model.add(\n",
        "    tf.keras.layers.Dense(\n",
        "        units=1, # Single unit\n",
        "        activation='sigmoid' # Sigmoid activation function (output from 0 to 1)\n",
        "    )\n",
        ")\n",
        "\n",
        "# Compile the model\n",
        "model.compile(\n",
        "    loss=tf.keras.losses.binary_crossentropy, # loss function\n",
        "    optimizer=tf.keras.optimizers.Adam(), # optimiser function\n",
        "    metrics=['accuracy']) # reporting metric\n",
        "\n",
        "# Display a summary of the models structure\n",
        "model.summary()"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Model: \"sequential_2\"\n",
            "_________________________________________________________________\n",
            "Layer (type)                 Output Shape              Param #   \n",
            "=================================================================\n",
            "embedding_2 (Embedding)      (None, 500, 32)           320000    \n",
            "_________________________________________________________________\n",
            "dropout_2 (Dropout)          (None, 500, 32)           0         \n",
            "_________________________________________________________________\n",
            "lstm (LSTM)                  (None, 32)                8320      \n",
            "_________________________________________________________________\n",
            "dropout_3 (Dropout)          (None, 32)                0         \n",
            "_________________________________________________________________\n",
            "dense (Dense)                (None, 1)                 33        \n",
            "=================================================================\n",
            "Total params: 328,353\n",
            "Trainable params: 328,353\n",
            "Non-trainable params: 0\n",
            "_________________________________________________________________\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8Xx1Q2I8WNI9"
      },
      "source": [
        "## Visualise the Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cz0Erj2WU3Vh",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 644
        },
        "outputId": "0b9d22da-1f99-4662-b535-51bbf9a12fc4"
      },
      "source": [
        "tf.keras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=False)"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "image/png": "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fpKSkrocXD6UBAYGIjAw0NRhsH6aM2cO5syZY+owdPibLWOMiYCTLWOMiYCTLWOMiYCTLWOMiYCTLWOMiWDARiMcOHBAMA8RGzjz58/vtXgy08fPIzMnkn+/ktYvp0+fRnl5+UDEw1iPTp8+jdTU1EGbf4uxe/n7+w9E6dCcAUm2jIklOzsb8+fPN+3EfYwZL4f7bBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAScbBljTAQ2pg6Ase7cunULf/vb3wTLvv32WwDA7t27BctVKhUWLFggWmyMGUtCRGTqIBjrSktLC0aOHIn6+npYW1sDADofV4lEomun1WqxZMkS/PWvfzVFmIwZIoe7EZjZkslkCAsLg42NDbRaLbRaLdra2tDW1qb7b61WCwBYuHChiaNlrGecbJlZW7hwIVpbW3ts4+DggN/97nciRcRY33CyZWbtySefhLOzc7frpVIpFi9eDBsb/vmBmTdOtsysWVlZYdGiRZBKpV2u12q1/MMYswicbJnZW7Bgga5v9l4PPPAA/Pz8RI6IMeNxsmVm77HHHoOXl5fecltbWyxZskQwMoExc8XJllmEZ599Vq8robW1lbsQmMXgZMsswqJFi/S6Enx8fDBp0iQTRcSYcTjZMovg6+uLCRMm6LoMpFIpnn/+eRNHxZjhONkyi/Hcc8/p3iRra2vjLgRmUTjZMouxYMECtLe3AwCmTp0Kb29vE0fEmOE42TKL4enpiV//+tcAgCVLlpg4GsaMM6iv3ezcuROnT58ezEOw+0xLSwskEglOnDiBL774wtThsCFkzZo1gzpme1C/2Z4+fRpff/31YB5iyDhw4ACuX79u6jDMnru7O1xcXCCXy/H111/z88UGxIEDB1BeXj6oxxj0F8qnT5+OnJycwT6MxZNIJFi9ejXmzZtn6lDM3sWLF+Hj44Pw8HAA4OeL9ZsYL8Zwny2zOD4+PqYOgTGjcbJljDERcLJljDER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\n",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 10
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5KdfAoHsGwzo"
      },
      "source": [
        "## Train the LSTM"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rEN1vV4nG1V3",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "d9dbba03-32c0-4aa5-e9a8-e5f6d29962d1"
      },
      "source": [
        "# Train the LSTM on the training data\n",
        "history = model.fit(\n",
        "\n",
        "    # Training data : features (review) and classes (positive or negative)\n",
        "    x_train, y_train,\n",
        "                    \n",
        "    # Number of samples to work through before updating the \n",
        "    # internal model parameters via back propagation. The \n",
        "    # higher the batch, the more memory you need.\n",
        "    batch_size=256, \n",
        "\n",
        "    # An epoch is an iteration over the entire training data.\n",
        "    epochs=3, \n",
        "    \n",
        "    # The model will set apart his fraction of the training \n",
        "    # data, will not train on it, and will evaluate the loss\n",
        "    # and any model metrics on this data at the end of \n",
        "    # each epoch.\n",
        "    validation_split=0.2,\n",
        "    \n",
        "    verbose=1\n",
        ") "
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Epoch 1/3\n",
            "79/79 [==============================] - 11s 42ms/step - loss: 0.6640 - accuracy: 0.6461 - val_loss: 0.5942 - val_accuracy: 0.7592\n",
            "Epoch 2/3\n",
            "79/79 [==============================] - 3s 37ms/step - loss: 0.4047 - accuracy: 0.8402 - val_loss: 0.3422 - val_accuracy: 0.8588\n",
            "Epoch 3/3\n",
            "79/79 [==============================] - 3s 37ms/step - loss: 0.2598 - accuracy: 0.9047 - val_loss: 0.2993 - val_accuracy: 0.8816\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rpCS2-jFH1KY"
      },
      "source": [
        "## Evaluate model with test data and view results"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nPnfxwbnITqV",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "8cf4f12d-f801-4317-a49f-c9ec2b0abbb9"
      },
      "source": [
        "# Get Model Predictions for test data\n",
        "# TODO \n",
        "from sklearn.metrics import classification_report\n",
        "predicted_classes = np.argmax(model.predict(x_test), axis=-1)\n",
        "print(classification_report(y_test, predicted_classes, target_names=class_names))"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "/opt/conda/lib/python3.7/site-packages/sklearn/metrics/_classification.py:1248: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
            "_warn_prf(average, modifier, msg_start, len(result))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "              precision    recall  f1-score   support\n",
            "\n",
            "    Negative       0.84      0.92      0.88     12500\n",
            "    Positive       0.91      0.82      0.86     12500\n",
            "\n",
            "    accuracy                           0.87     25000\n",
            "   macro avg       0.87      0.87      0.87     25000\n",
            "weighted avg       0.87      0.87      0.87     25000\n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CkfHCIVHrJni"
      },
      "source": [
        "## View some incorrect predictions\n",
        "\n",
        "Let's have a look at some of the incorrectly classified reviews. For readability we remove the padding.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bwKLBwBbp7zg",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "75830a56-10dd-4a3e-c013-8272328ba1aa"
      },
      "source": [
        "predicted_classes_reshaped = np.reshape(predicted_classes, 25000)\n",
        "\n",
        "incorrect = np.nonzero(predicted_classes_reshaped!=y_test)[0]\n",
        "\n",
        "# We select the first 10 incorrectly classified reviews\n",
        "for j, incorrect in enumerate(incorrect[0:20]):\n",
        "    \n",
        "    predicted = class_names[predicted_classes_reshaped[incorrect]]\n",
        "    actual = class_names[y_test[incorrect]]\n",
        "    human_readable_review = decode_review(x_test[incorrect])\n",
        "    \n",
        "    print(\"Incorrectly classified Test Review [\"+ str(j+1) +\"]\") \n",
        "    print(\"Test Review #\" + str(incorrect)  + \": Predicted [\"+ predicted + \"] Actual [\"+ actual + \"]\")\n",
        "    print(\"Test Review Text: \" + human_readable_review.replace(\"<PAD> \", \"\"))\n",
        "    print(\"\")"
      ],
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Incorrectly classified Test Review [1]\n",
            "Test Review #5: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> i'm absolutely disgusted this movie isn't being sold all who love this movie should email disney and increase the demand for it they'd eventually have to sell it then i'd buy copies for everybody i know everything and everybody in this movie did a good job and i haven't figured out why disney hasn't put this movie on dvd or on vhs in rental stores at least i haven't seen any copies this is a wicked good movie and should be seen by all the kids in the new generation don't get to see it and i think they should it should at least be put back on the channel this movie doesn't deserve a cheap <UNKNOWN> it deserves the real thing i'm them now this movie will be on dvd\n",
            "\n",
            "Incorrectly classified Test Review [2]\n",
            "Test Review #8: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> hollywood had a long love affair with bogus <UNKNOWN> nights tales but few of these products have stood the test of time the most memorable were the jon hall maria <UNKNOWN> films which have long since become camp this one is filled with dubbed songs <UNKNOWN> <UNKNOWN> and slapstick it's a truly crop of corn and pretty near <UNKNOWN> today it was nominated for its imaginative special effects which are almost <UNKNOWN> in this day and age <UNKNOWN> mainly of trick photography the only outstanding positive feature which survives is its beautiful color and clarity sad to say of the many films made in this genre few of them come up to alexander <UNKNOWN> original thief of <UNKNOWN> almost any other <UNKNOWN> nights film is superior to this one though it's a loser\n",
            "\n",
            "Incorrectly classified Test Review [3]\n",
            "Test Review #22: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> how managed to avoid attention remains a mystery a potent mix of comedy and crime this one takes chances where tarantino plays it safe with the hollywood formula the risks don't always pay off one character in one sequence comes off <UNKNOWN> silly and falls flat in the lead role thomas jane gives a wonderful and complex performance and two brief appearances by mickey rourke hint at the high potential of this much under and <UNKNOWN> used actor here's a director one should keep one's eye on\n",
            "\n",
            "Incorrectly classified Test Review [4]\n",
            "Test Review #32: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> if you have never read the classic science fiction novel this mini series is based on it may actually be good unfortunately if you are a fan of the book you probably won't be able to watch more than the first hour or two all of the political intrigue has been taken out of the film the most important scenes from the book have been taken out characters motivations have been changed completely and words from the wrong characters mouths where in the novel paul was a teen age boy with incredible political skill and a great understanding of the way the world worked in this film he is hot headed and and frustrated avoid this movie at all costs\n",
            "\n",
            "Incorrectly classified Test Review [5]\n",
            "Test Review #49: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> i can't understand why imdb users would rate this movie 5 2 10 it really is great very funny i would strongly recommend this movie for all of you adults teenagers and especially children br br the story is about a 14 year old kid who always tell lie at home and school one day he had his <UNKNOWN> of writing a 1000 word story but he didn't so the teacher told him to write it and gave her in 3 hours or he would have to go to summer school yep he wrote it in 2 45 big fat liar i think it was a story of himself on the way to the school he hit a <UNKNOWN> of a famous hollywood producer and he gave him a ride but the kid forgot the story in the <UNKNOWN> he told his parents and the teacher but of course they did not believe him and the movie producer he took the kid's story as his new movie big fat liar when the kid saw the trailer of the movie he told his parents he had written it but they didn't believe so he and his friend had to go to l a to prove one thing the truth is never overrated br br enjoy this great movie you won't be disappointed don't trust the 5 2 10 rate it should be 9 10 believe me br br p s so sorry my english isn't good enough to make a better comment\n",
            "\n",
            "Incorrectly classified Test Review [6]\n",
            "Test Review #66: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: forgive me if i don't phrase this correctly i was extremely disappointed that there were no optimistic overtones at all yes we all know that life is full of hard stuff and yes we know that things such as incest do occur but i really find it hard to applaud a movie that has not one piece of joy in it i believe that a director has a responsibility to put it in there somewhere otherwise the movie is all about them and their feelings they have created it for themselves not for an audience br br which i think is the basis of why this movie isn't so great the special features mention that the director wrote the screenplay in a <UNKNOWN> hour sitting the day after he himself tried to end his own life well it may have been <UNKNOWN> for him to do this however the movie <UNKNOWN> of self <UNKNOWN> when you know the story behind why it was written i feel horrid i'm going to write a movie about feeling horrid note i have read the interview with andrew urban and understand why needed to write something to help him through his own issues but i believe there is a line in film that cannot be crossed the line of making a movie purely for your own emotional needs and i feel that this is what has unintentionally happened here br br by his own admission the director had no technical experience at all and sadly this makes the movie come off looking like nothing more than a year twelve media project br br as for any <UNKNOWN> that this movie should be studied at school or that all teenagers should watch it not sure there either because there is a very dangerous line at the end i too have been in a place where i have thought that someone who no longer has to <UNKNOWN> <UNKNOWN> is <UNKNOWN> but as an adult i do worry that this line could be influential on a young viewer that was in a vulnerable frame of mind might be in there to promote discussion but again it reflects no possibility of redemption or joy in this story as a whole in fact it almost <UNKNOWN> that there is more sadness to come br br i haven't seen elephant but i just might go find it given all the comparisons here br br nothing personal here guys i do hope you can make another movie someday and we all have to start out somewhere so forgive me if i've been too harsh i am glad that you are proud of what you created which in the end is what life is all about it's not a movie i would recommend though br br oh i did like the way the time frames often <UNKNOWN> thought that was an interesting way to film br br but the whole its the quiet ones you have to watch we already know that\n",
            "\n",
            "Incorrectly classified Test Review [7]\n",
            "Test Review #80: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> with the obvious exception of fools horses this was in my opinion david <UNKNOWN> finest series br br coming straight after his tv debut on <UNKNOWN> not <UNKNOWN> your set ' these 13 episodes revealed a <UNKNOWN> of comic timing not seen since the old silent movie days by comparison <UNKNOWN> open all hours and that awful series <UNKNOWN> man' did not come close br br i believe jason banned the series being repeated because it showed him at his <UNKNOWN> shame on him a new generation deserves to enjoy this the series actually <UNKNOWN> in the ratings but that is most likely because it was shown against 'the <UNKNOWN> which aired on bbc at the same time before <UNKNOWN> were <UNKNOWN> br br btw i have only just noticed that his long suffering assistant spencer was played by mark <UNKNOWN> alan <UNKNOWN> off <UNKNOWN> street i am amazed he didn't try to murder edgar <UNKNOWN>\n",
            "\n",
            "Incorrectly classified Test Review [8]\n",
            "Test Review #100: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> a quick glance at the premise of this film would seem to indicate just another dumb <UNKNOWN> <UNKNOWN> <UNKNOWN> slash fest the type where sex equals death and the actors are all annoying stereotypes you actually want to die however delivers considerably more br br rather than focus on bare flesh and gore though there is a little of each no sex however the flick focuses on delivering impending dread <UNKNOWN> tension amidst a lovely <UNKNOWN> backdrop these feelings are further <UNKNOWN> by a cast of realistically likable characters and <UNKNOWN> that are more amoral than cardboard <UNKNOWN> of evil oh yeah george kennedy is here too and when is that not a good thing br br if you liked wrong turn then watch this to see where much of its' <UNKNOWN> came from\n",
            "\n",
            "Incorrectly classified Test Review [9]\n",
            "Test Review #101: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> <UNKNOWN> is the first of its kind in turkish cinema and it's way better than i expected those people who say it's neither scary nor funny have a point it's not all that great indeed but it must be kept in mind that everyone involved with the movie is rather amateur so it's basically a maiden voyage and comparing this one to other films such as the 1st class garbage propaganda this movie is pretty damn good br br one thing that must be said it deals with the <UNKNOWN> <UNKNOWN> life in turkey very realistically that's exactly how it goes the scenes that are meant to scare are somewhat cheap and <UNKNOWN> most of them even if not all but that religion lesson scene made me laugh in tears and performs the best acting of this flick as a religion teacher br br it's not a waste of your time go and watch it you'll find it rather amusing especially if you know turkey enough to relate to turkish school lives\n",
            "\n",
            "Incorrectly classified Test Review [10]\n",
            "Test Review #112: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> if you want to see a horror film which is horrible and in very bad taste this is definitely the film to view this films starts out with two young teenagers getting wild ideas about going into a chat room and going out on blind dates and quite possibly they will wind up like a little <UNKNOWN> to the slaughter house plenty of blood gore nudity <UNKNOWN> and all kinds of blood <UNKNOWN> <UNKNOWN> and things you will never dream a person is capable of performing on men and women if you like <UNKNOWN> well this kind of <UNKNOWN> deals with heavy heavy <UNKNOWN> and plenty of besides lots of <UNKNOWN> and thread to seal up things on the human body i really hope that this film does not give some sick person in this world the idea to act out these horrors in real life\n",
            "\n",
            "Incorrectly classified Test Review [11]\n",
            "Test Review #115: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> while the design and locations and photography are strong <UNKNOWN> in this film it is a turgid and melodramatic affair which demonstrates the limits of cinema to convey truth br br the case is the use of the soundtrack music a mix of <UNKNOWN> and andrew lloyd <UNKNOWN> that plays constantly and <UNKNOWN> and would have made max <UNKNOWN> <UNKNOWN> at its over use as it <UNKNOWN> the audience how difficult how <UNKNOWN> how tortured it is to be an artist and then it really counts the story the details at the end br br this <UNKNOWN> and <UNKNOWN> exploitation of emotions was once well <UNKNOWN> by peter <UNKNOWN> about a <UNKNOWN> <UNKNOWN> book this is not writing this is barbara <UNKNOWN> precisely the same critique can be made of this film a <UNKNOWN> <UNKNOWN> vanity project\n",
            "\n",
            "Incorrectly classified Test Review [12]\n",
            "Test Review #126: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> this was answer to fatal attraction and this is a classic film in its own right <UNKNOWN> <UNKNOWN> was good and so was sunny <UNKNOWN> but it was shah rukh khan who shot to fame as the stalker since then he has become a favourite of the <UNKNOWN> <UNKNOWN> <UNKNOWN> le <UNKNOWN> <UNKNOWN> to <UNKNOWN> <UNKNOWN> <UNKNOWN> <UNKNOWN> and de india shah rukh at first appears to be a villain but then towards the end you start to sympathize with him the scripting was superb and the songs were my favourites are too mere and <UNKNOWN> br br after the dismal failure of the underrated <UNKNOWN> <UNKNOWN> fought back with <UNKNOWN> the dialogues were memorable the k k <UNKNOWN> dialogue is often repeated since <UNKNOWN> <UNKNOWN> <UNKNOWN> has slipped bit <UNKNOWN> to <UNKNOWN> <UNKNOWN> was bad but he redeemed himself slightly with <UNKNOWN> <UNKNOWN> which was far far better this was <UNKNOWN> <UNKNOWN> last masterpiece\n",
            "\n",
            "Incorrectly classified Test Review [13]\n",
            "Test Review #130: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> i just saw this movie at the berlin film <UNKNOWN> children's program and it just killed me and pretty much everyone else in the audience and make no mistake about it this film belongs into the all time 250 let me tell you that i'm in no way associated with the creators of this film if that's what you come to believe reading this no but this actually is it <UNKNOWN> the kid's film label on it <UNKNOWN> girl is on almost every account a classic as in biblical the story concerns 12 year old <UNKNOWN> <UNKNOWN> julie who is <UNKNOWN> to learn of her <UNKNOWN> <UNKNOWN> illness special surgery in the us would cost 1 5 million and of course nobody could afford that so <UNKNOWN> and her friends <UNKNOWN> and sebastian do what every good kid would and <UNKNOWN> a bank sounds corny don't forget this is not america and is by no means the tear <UNKNOWN> robin williams <UNKNOWN> <UNKNOWN> du <UNKNOWN> nobody takes seriously anyway director <UNKNOWN> set out to make a big budget action comedy for kids and boy did he succeed let me put it this way this film rocks like no kid film and few others did before and there's a whole lot more to it than just the action after about 20 minutes of by the numbers exposition well granted it into a monster that br br effortlessly puts mission impossible to shame the numerous action sequences are masterfully staged and look real expensive take that mummy br br <UNKNOWN> almost every other movie suspense wise no easy they're only kids antics here br br easily <UNKNOWN> a dense story with enough laughs to make jim carrey look for career <UNKNOWN> br br <UNKNOWN> to both damon <UNKNOWN> and karate kid within the same seconds br br comes up with so much wicked humor that side of p c that i can hear the american ratings board wet their pants from over here br br manages to actually be tender and serious and sexy at the same time what am i saying they're kids they're kids <UNKNOWN> watch that last scene br br stars <UNKNOWN> anderson who since last years is everybody's favourite kid actor br br what a ride\n",
            "\n",
            "Incorrectly classified Test Review [14]\n",
            "Test Review #146: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> i was shocked to learn that jimmy <UNKNOWN> has left this show does anyone know why i regard james as one of the all time <UNKNOWN> and wasn't surprised he ended up on tv which can be better than the crap you see on the big screen the stories are slick and the camera faster than a <UNKNOWN> bullet <UNKNOWN> forget the rest of the cast james vanessa <UNKNOWN> <UNKNOWN> molly josh mitch also can anyone tell me why on earth there's a crap theme tune on the dvd sets but <UNKNOWN> <UNKNOWN> of a little less conversation is used on the initial nbc <UNKNOWN> does it not make sense to use a tune that you would associate with the gambling <UNKNOWN> of america for dvd releases\n",
            "\n",
            "Incorrectly classified Test Review [15]\n",
            "Test Review #147: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> having enjoyed neil <UNKNOWN> writing especially his collaboration with <UNKNOWN> in the dream hunters in the past i figured <UNKNOWN> to be a sure thing and was very disappointed the beginning live action section of the movie was intriguing enough the relationships between the characters was believable and easy to empathize with and i loved the sets the <UNKNOWN> and <UNKNOWN> artwork the subsequent computer generated scenes however were excruciating the dialogue was awkward and pretentious the interaction between the live actors and the cgi horrifying events occurred for the <UNKNOWN> reasons and most events seemed superfluous to whatever plot may have existed i only watched the first twenty or thirty minutes of the movie so i'm not exactly an authority but i strongly recommend that you don't watch any of it at all and stick with <UNKNOWN> strong written work\n",
            "\n",
            "Incorrectly classified Test Review [16]\n",
            "Test Review #152: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> i can pretend no knowledge of cinematography or mr <UNKNOWN> but i know <UNKNOWN> and i love her people in july my 14 year old son and i traveled to turkey in search of some remains of the neighborhood where his great grandfather lived until the great <UNKNOWN> of <UNKNOWN> in <UNKNOWN> reading the summary of the film <UNKNOWN> from <UNKNOWN> i thought that perhaps i might learn something more about the forced <UNKNOWN> of modern <UNKNOWN> if i did not have a home in <UNKNOWN> had i not been to <UNKNOWN> 28 times in as many years were i not familiar with dozens of islands and cities in <UNKNOWN> and if i had never enjoyed the friendship of these <UNKNOWN> life <UNKNOWN> people i might have believed that this had something to do with modern <UNKNOWN> as a professor at a new jersey state college let me assure you that i am familiar with the history of the period covered in the film indeed my wife's uncle was murdered by the <UNKNOWN> during the communist grab for power my mother in law lived through the italian invasion and german <UNKNOWN> barely these characters on the screen speak greek they listen to greek music but who are they no they are not even vaguely greek of course they are not people at all but simply <UNKNOWN> they are that which the artist <UNKNOWN> when life does not entirely fit or is <UNKNOWN> to his perception of how it was or should have been all represent some aspect of post wwi <UNKNOWN> that greater outside forces <UNKNOWN> to a fate they didn't deserve as we <UNKNOWN> in the late 70's in america the revolution didn't happen for an <UNKNOWN> artist this is no joke it's in fact grounds to put us through two and a half hours of torment and it's all because the various powers <UNKNOWN> of guards in different colored uniforms didn't allow the generation after the <UNKNOWN> of <UNKNOWN> to follow the call of peace and freedom the music of <UNKNOWN> and his fellow musicians i e the movement the cause this dark surreal <UNKNOWN> <UNKNOWN> the true and heroic efforts of the greek people to sustain their lust for life through the <UNKNOWN> of the 20th century to achieve more than any of their <UNKNOWN> neighbors to have become so politically evolved and <UNKNOWN> integrated\n",
            "\n",
            "Incorrectly classified Test Review [17]\n",
            "Test Review #154: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> i saw this movie many years ago and just for kicks decided to rent it and watch it again the plot is a <UNKNOWN> copy from fright night i did like the hairy vampire and the bug eating driver otherwise it was not good at all\n",
            "\n",
            "Incorrectly classified Test Review [18]\n",
            "Test Review #156: Predicted [Positive] Actual [Negative]\n",
            "Test Review Text: <START> i rented this when it came out on video <UNKNOWN> in 1995 after <UNKNOWN> it again my idea about it hasn't changed much br br i was an adult then and i'm still an adult now lol br br the illogical elements mentioned by other reviewers didn't bother me this isn't a documentary it's a fantasy story where animals can talk br br while i didn't care for much of the songs i liked the one at the end of the picture where it's sang by barry <UNKNOWN> and another person br br some people seem to make an excuse for it's primitive animation by saying that cgi wasn't used often in animated features but let's not forget that the lion king was released about a year earlier and that packed possibly more excellence than any animated feature that came before it br br but i think it's pretty fair to say that the <UNKNOWN> and the was made on the cheap while the lion king wasn't br br the high points for me in 1995 as well as today is the suspense generated by the few dangerous mostly underwater chase scenes br br i also liked the opening scene which takes place on a music notes page and a little bit of the love story but most of the time the story dragged on and was boring br br worth a look if you like animation but if you're an adult and not a risk taker go get another walt disney production instead of this\n",
            "\n",
            "Incorrectly classified Test Review [19]\n",
            "Test Review #159: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: predictable and based largely around glaring cliché borrowed <UNKNOWN> from the likes of <UNKNOWN> killer and john <UNKNOWN> classic the killer br br almost every aspect of the film is <UNKNOWN> with angst with the three lead characters suffering as if the weight of the world was on their shoulders and <UNKNOWN> <UNKNOWN> to do anything to pursue their romantic <UNKNOWN> park <UNKNOWN> in particular as the kind of overly emotional socially retarded assassin so beloved of modern cinema is <UNKNOWN> ludicrous from his blatant incompetence on the job to his hilarious attempts to discuss <UNKNOWN> painting with young or his <UNKNOWN> for flower growing this <UNKNOWN> <UNKNOWN> does make the film's central romance somewhat hard to swallow and <UNKNOWN> attempts to evoke the feeling that it is fate which brings the characters together comes across more as shoddy coincidence br br fans of <UNKNOWN> <UNKNOWN> <UNKNOWN> should note that her character is far closer to her role in the <UNKNOWN> supernatural drama the <UNKNOWN> than my sassy girl or and while she tries her best to pull a few wacky faces here and there her performance is certainly more subdued br br the film benefits from glossy production values and <UNKNOWN> makes good use of the <UNKNOWN> scenery playing on the contrast between the grey almost gothic beauty of the city and the innocent blue <UNKNOWN> and <UNKNOWN> fields of the countryside unfortunately he tends to <UNKNOWN> slow motion for some of the emotional scenes which when coupled with some of the picture <UNKNOWN> visuals gives the film the feel at times of a <UNKNOWN> <UNKNOWN> there are a few scenes of surprisingly violent action though these are few and far between and whilst well staged seem to have been thrown in as an <UNKNOWN> and do little more than briefly raising the pulse br br despite its flaws daisy makes for engaging viewing and the story grips almost in spite of itself mainly out of a morbid fascination to see not which of the men young will end up with but to see who will lie dying in her arms the self indulgent melodrama works well enough to <UNKNOWN> all the right boxes for the genre and the film functions perfectly well as an <UNKNOWN> glossy <UNKNOWN> romance br br it is worth noting that the dvd features the director's cut of the film which for once <UNKNOWN> that it is <UNKNOWN> different from the theatrical version which not only adds 25 minutes but some of the scenes making the narrative less linear although this new version is perhaps too long it is surely superior as without these changes the film would surely have been even more conventional and would have suffered from even <UNKNOWN> character development br br <UNKNOWN> <UNKNOWN> <UNKNOWN> director young screenplay cast woo sung <UNKNOWN> park <UNKNOWN> sung lee  <UNKNOWN> woo david <UNKNOWN><UNKNOWN> ho <UNKNOWN> <UNKNOWN>  etective <UNKNOWN> <UNKNOWN> <UNKNOWN> <UNKNOWN>yung <UNKNOWN> <UNKNOWN>  UKNOWN> <UNKNOWN> ha\n",
            "\n",
            "Incorrectly classified Test Review [20]\n",
            "Test Review #167: Predicted [Negative] Actual [Positive]\n",
            "Test Review Text: <START> for all viewers out there who have <UNKNOWN> john waters for creating a film like pink <UNKNOWN> just stop it's getting you nowhere has anyone ever cared to stop and think about the ambition and dedication mr waters possesses to gather your best friends up and to create a movie just to gross out thousands of viewers all over shows this man has a great deal of ambition inside himself just read his biography shock value it <UNKNOWN> the <UNKNOWN> he went through to get this film finished maybe it wasn't just the fact that john made this film to gross people out it was to prove that there can be something such as good bad taste\n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OlAfxIoTrtYa"
      },
      "source": [
        "## Run your own text against the trained model\n",
        "\n",
        "This is a fun way to test out the limits of the trained model. To avoid getting errors - type in lower case only and do not use punctuation! \n",
        "\n",
        "You'll see the raw prediction from the model - basically a value between 0 and 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "UEKEB0DpD_8P",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "975a5f72-6253-4a83-f403-ad1fc58ced92"
      },
      "source": [
        "# Write your own review\n",
        "review = \"this was a terrible film with too much sex and violence i walked out halfway through\"\n",
        "#review = \"this is the best film i have ever seen it is great and fantastic and i loved it\"\n",
        "#review = \"this was an awful film that i will never see again\"\n",
        "\n",
        "# Encode review (replace word with integers)\n",
        "tmp = []\n",
        "for word in review.split(\" \"):\n",
        "    tmp.append(word_index[word])\n",
        "\n",
        "# Ensure review is 500 words long (by padding or truncating)\n",
        "tmp_padded = sequence.pad_sequences([tmp], maxlen=review_length) \n",
        "\n",
        "# Run your processed review against the trained model\n",
        "rawprediction = model.predict(array([tmp_padded][0]))[0][0]\n",
        "prediction = int(round(rawprediction))\n",
        "\n",
        "# Test the model and print the result\n",
        "print(\"Review: \" + review)\n",
        "print(\"Raw Prediction: \" + str(rawprediction))\n",
        "print(\"Predicted Class: \" + class_names[prediction])"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Review: this was a terrible film with too much sex and violence i walked out halfway through\n",
            "Raw Prediction: 0.24618092\n",
            "Predicted Class: Negative\n"
          ],
          "name": "stdout"
        }
      ]
    }
  ]
}
